/*
 * Copyright 2011 David Scherzinger, Joe Quinn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package pisa.puzzle;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.Stroke;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;

import javax.swing.JPanel;

public class Puzzle extends JPanel {
	public static final int CELL_INTERIOR = 20;
	public static final int MARGIN = 20;
	public static final int FONT_SIZE = 10;
	private double zoom = 1;
	private int xCells = 0, yCells = 0;
	private String puzzleType;

	// When making clues, use references to the styles in these
	// ArrayLists to save on memory
	private ArrayList<Stroke> borders;
	private ArrayList<Stroke> paths;
	private ArrayList<Color> fills;

	private Stroke[][] horizontalBorders = null, verticalBorders = null;
	private Stroke[][] horizontalPaths = null, verticalPaths = null;
	// Clues are kind of big, and fairly sparse, so they don't get an array
	private LinkedList<Clue> centerClues = null, edgeClues = null, cornerClues = null;

	public Puzzle() {
		super();
		setBackground(Color.WHITE);
		fills.set(0, Color.WHITE);

	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(fills.get(0));
		int zoomMargin = (int)(MARGIN*zoom);
		int zoomCellWidth = (int)(CELL_INTERIOR*zoom);

		// Proper layering:
		// Top  Edge/Corner clues
		//      Borders
		//      Paths
		//      Cell-centered clues
		// Bot  Background

		// Background
		g.fillRect(zoomMargin, zoomMargin, zoomCellWidth*xCells, zoomCellWidth*yCells);

		// Cell-centered clues
		if(centerClues != null) {
			Iterator<Clue> it = centerClues.iterator();
			while(it.hasNext()) {
				it.next().draw(g, zoom, zoomMargin, zoomCellWidth);
			}
		}

		// Paths
		// TODO Incorporate multiple colors/strokes
		g.setColor(Color.BLACK);
		if(horizontalPaths != null) {
			// Horizontal paths
			for(int i = 0; i < yCells; i++) {
				for(int j = 0; j < xCells-1; j++) {
					int startX = j*zoomCellWidth+zoomCellWidth/2+zoomMargin;
					int startY = i*zoomCellWidth+zoomCellWidth/2+zoomMargin;
					g.drawLine(startX, startY,
							startX+zoomCellWidth, startY);
				}
			}
			// Vertical paths
			for(int i = 0; i < yCells-1; i++) {
				for(int j = 0; j < xCells; j++) {
					int startX = j*zoomCellWidth+zoomCellWidth/2+zoomMargin;
					int startY = i*zoomCellWidth+zoomCellWidth/2+zoomMargin;
					g.drawLine(startX, startY,
							startX, startY+zoomCellWidth);
				}
			}
		}

		// Borders
		// TODO Incorporate multiple colors/strokes
		g.setColor(Color.BLACK);
		if(horizontalBorders != null) {
			// Horizontal borders
			for(int i = 0; i <= yCells; i++) {
				for(int j = 0; j < xCells; j++) {
					int startX = j*zoomCellWidth+zoomMargin;
					int startY = i*zoomCellWidth+zoomMargin;
					g.drawLine(startX, startY,
							startX+zoomCellWidth, startY);
				}
			}
			// Vertical borders
			for(int i = 0; i < yCells; i++) {
				for(int j = 0; j <= xCells; j++) {
					int startX = j*zoomCellWidth+zoomMargin;
					int startY = i*zoomCellWidth+zoomMargin;
					g.drawLine(startX, startY,
							startX, startY+zoomCellWidth);
				}
			}
		}
		else {
			// Horizontal borders
			for(int i = 0; i <= yCells; i++) {
				g.drawLine(zoomMargin, zoomMargin,
						xCells*zoomCellWidth+zoomMargin, zoomMargin);
			}
			// Vertical borders
			for(int i = 0; i <= xCells; i++) {
				g.drawLine(zoomMargin, zoomMargin,
						zoomMargin, yCells*zoomCellWidth+zoomMargin);
			}
		}
		
		// Edge clues
		if(edgeClues != null) {
			Iterator<Clue> it = edgeClues.iterator();
			while(it.hasNext()) {
				it.next().draw(g, zoom, zoomMargin, zoomCellWidth);
			}
		}
		
		// Corner clues
		if(cornerClues != null) {
			Iterator<Clue> it = cornerClues.iterator();
			while(it.hasNext()) {
				it.next().draw(g, zoom, zoomMargin, zoomCellWidth);
			}
		}
	}

	public void setGridSize(int xCells, int yCells) {
		this.xCells = xCells;
		this.yCells = yCells;
	}
}